import 'package:flutter/material.dart';
import 'package:qunaimedical/components/custom_divider.dart';
import 'package:qunaimedical/components/item_doctor.dart';
import 'package:qunaimedical/components/primary_button.dart';
import 'package:qunaimedical/components/search_bar.dart';
import 'package:qunaimedical/models/area.dart';
import 'package:qunaimedical/models/consultaion_post_bean.dart';
import 'package:qunaimedical/models/department.dart';
import 'package:qunaimedical/models/doctor.dart';
import 'package:qunaimedical/models/hospital.dart';
import 'package:qunaimedical/models/list_response.dart';
import 'package:qunaimedical/models/user.dart';
import 'package:qunaimedical/network/http.dart';
import 'package:qunaimedical/pages/home.dart';
import 'package:qunaimedical/utils/common_util.dart';
import 'package:qunaimedical/utils/dialog_utils.dart';
import 'package:qunaimedical/utils/log_utils.dart';
import 'package:qunaimedical/utils/sp_utils.dart';
import 'package:qunaimedical/utils/toast_util.dart';
import 'package:qunaimedical/values/urls.dart';
import 'package:sprintf/sprintf.dart';

/// 选择医生界面
class SelectDoctorPage extends StatefulWidget {
  final ConsultationPostBean bean;

  const SelectDoctorPage(this.bean, {Key key}) : super(key: key);

  @override
  _SelectDoctorPageState createState() => _SelectDoctorPageState();
}

class _SelectDoctorPageState extends State<SelectDoctorPage> {
  String _tag = '_SelectDoctorPageState';

  /// 所有医生列表
  List<Doctor> _allItems = [];

  /// 医生列表
  List<Doctor> _items = [];

  /// 选中的医生
  List<Doctor> _selectedDoctorList = [];

  /// 医院列表
  List<Hospital> _allHospitalList = [];

  /// 医院列表
  List<Hospital> _hospitalList = [];

  /// 地区列表
  List<Area> _areaList = [];

  /// 分组后的地区列表数据
  Map<Area, List<Area>> areaSets = {};

  /// 科室列表。
  List<Department> _departments = [];

  /// 预约类型
  List<String> _selectedTypes = ['全部', '未约', '已约'];

  /// 传递过来的数据
  ConsultationPostBean _bean;

  /// 已选预约类型
  int _selectedType = 0;

  /// 已选的地区索引
  List<int> _selectedAreaIndex = [-1, -1];

  /// 已选择的医院索引
  int _selectedHospitalIndex;

  /// 已选择的科室索引
  int _selectedDepartmentIndex;

  /// 选择器key
  GlobalKey selectorKey = GlobalKey();

  TextEditingController _controller = TextEditingController();

  @override
  void initState() {
    super.initState();
    _bean = widget.bean;
    Log.d(_tag, _bean);
    _fetchDoctorList();
    _fetchHospitalList();
    _fetchAreaList();
    _getDepartmentTypes();
  }

  @override
  void dispose() {
    super.dispose();
    _controller.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('选择医生')),
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          _buildSearchBar(),
          _buildSelector(context),
          CustomDivider(),
          Expanded(
            child: ListView.builder(
              itemBuilder: (c, i) {
                return ItemDoctor(
                  _items[i],
                  showCheckbox: true,
                  onCheckboxTap: () {
                    if (_selectedDoctorList
                        .map((e) => e.id)
                        .contains(_items[i].id)) {
                      // 点击当前按钮
                      _selectedDoctorList
                          .removeWhere((element) => element.id == _items[i].id);
                    } else {
                      // 点击其他按钮
                      _selectedDoctorList.add(_items[i]);
                    }
                    setState(() {
                      _items[i].selected = !(_items[i].selected ?? false);
                    });
                  },
                  onFavorite: () {
                    if (_items[i].whetherAppointed == '0') {
                      _addFavorite(i);
                    } else {
                      _removeFavorite(i);
                    }
                  },
                );
              },
              itemCount: _items.length,
            ),
          ),
          PrimaryButton(
            '预约',
            onPressed: () {
              if (_selectedDoctorList.isEmpty) {
                ToastUtil.show('请选择一名医生', context);
              } else {
                _post();
              }
            },
          ),
        ],
      ),
    );
  }

  Container _buildSelector(BuildContext context) {
    return Container(
      color: Colors.white,
      child: Row(
        key: selectorKey,
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        children: [
          _buildSection(
            _selectedTypes[_selectedType],
            onTap: () {
              _showSelectorDialog(context, null);
            },
          ),
          _buildSection(
            _selectedAreaIndex[0] == -1
                ? '地区'
                : '${areaSets.keys.toList()[_selectedAreaIndex[0]].name}${_selectedAreaIndex[1] == -1 ? '' : areaSets[areaSets.keys.toList()[_selectedAreaIndex[0]]][_selectedAreaIndex[1]].name}',
            onTap: () {
              if (areaSets.isEmpty) {
                return;
              }
              _showSelectorDialog(context, SelectorType.area);
            },
          ),
          _buildSection(
            _selectedHospitalIndex == null
                ? '医院'
                : _hospitalList[_selectedHospitalIndex].hospitalName,
            onTap: () {
              _showSelectorDialog(context, SelectorType.hospital);
            },
          ),
          _buildSection(
            _selectedDepartmentIndex == null
                ? '科室'
                : _departments[_selectedDepartmentIndex].label,
            onTap: () {
              if (_departments.isEmpty) {
                return;
              }
              _showSelectorDialog(context, SelectorType.department);
            },
          ),
        ],
      ),
    );
  }

  Container _buildSearchBar() {
    return Container(
      padding: EdgeInsets.only(left: 16, top: 16, right: 16, bottom: 5),
      color: Colors.white,
      child: SearchBar(
        hintText: '输入医生姓名搜索',
        controller: _controller,
        onSubmitted: (value) {
          if (value.isNotEmpty) {
            _fetchDoctorList(condition: {'fullname': value});
          } else {
            _fetchDoctorList();
          }
        },
      ),
    );
  }

  void _showSelectorDialog(BuildContext context, SelectorType type) {
    CommonUtils.hideKeyboard(context);
    showGeneralDialog(
        context: context,
        barrierLabel: "",
        barrierDismissible: true,
        barrierColor: Colors.transparent,
        transitionDuration: Duration(milliseconds: 0),
        transitionBuilder: _buildMaterialDialogTransitions,
        pageBuilder: (BuildContext context, Animation animation,
            Animation secondaryAnimation) {
          RenderBox renderBox =
              selectorKey.currentContext.findRenderObject() as RenderBox;
          Offset position = renderBox.localToGlobal(Offset.zero);
          return StatefulBuilder(builder: (context1, state) {
            Widget widget;
            switch (type) {
              case SelectorType.area:
                widget = _buildAreaSelector(state, context);
                break;
              case SelectorType.hospital:
                widget = _buildHospitalArea(state, context);
                break;
              case SelectorType.department:
                widget = _buildDepartmentSelector(state, context);
                break;
              default:
                widget = _buildSelectSelector(null, context);
            }
            return Padding(
              padding: EdgeInsets.only(
                top: kToolbarHeight + position.dy,
              ),
              child: Material(
                clipBehavior: Clip.antiAlias,
                child: Column(
                  children: [
                    Container(
                      decoration: BoxDecoration(
                          color: Colors.white,
                          border: Border(
                              bottom: BorderSide(color: Colors.grey[300]))),
                      height: 300,
                      child: widget,
                    ),
                    Expanded(
                      child: InkWell(
                        child: Container(),
                        onTap: () {
                          Navigator.pop(context);
                        },
                      ),
                    ),
                  ],
                ),
              ),
            );
          });
        }).whenComplete(() {
      // 选择完地区，重新获取医院列表
      if (type == SelectorType.area) {
        _fetchHospitalList();
        _fetchDoctorList();
      }
    });
  }

  /// 地区选择器
  Widget _buildAreaSelector(StateSetter state, BuildContext context) {
    return Row(
      children: [
        // 省
        Expanded(
          child: ListView.separated(
            itemBuilder: (c, i) {
              return InkWell(
                onTap: () {
                  // 选择地区后，重置选择的医院
                  _selectedHospitalIndex = null;
                  state(() {
                    _selectedAreaIndex[0] = i;
                    _selectedAreaIndex[1] = -1;
                    Log.d(_tag, _selectedAreaIndex);
                  });
                },
                child: Container(
                  child: Text(
                    '${areaSets.keys.toList()[i].name}',
                    style: TextStyle(
                      color: i == _selectedAreaIndex[0]
                          ? Theme.of(context).primaryColor
                          : Colors.black87,
                    ),
                  ),
                  alignment: Alignment.centerLeft,
                  margin: EdgeInsets.symmetric(horizontal: 16),
                  height: 50,
                ),
              );
            },
            itemCount: areaSets.keys.length,
            separatorBuilder: (BuildContext context, int index) => Divider(),
            padding: EdgeInsets.all(0),
          ),
        ),
        VerticalDivider(),
        // 市
        Expanded(
          child: ListView.separated(
            itemBuilder: (c, i) {
              return InkWell(
                onTap: () {
                  // 选择地区后，重置选择的医院
                  _selectedHospitalIndex = null;
                  state(() {
                    _selectedAreaIndex[1] = i;
                    Log.d(_tag, _selectedAreaIndex);
                    Navigator.pop(context);
                  });
                },
                child: Container(
                  height: 50,
                  alignment: Alignment.centerLeft,
                  margin: EdgeInsets.symmetric(horizontal: 16),
                  child: Text(
                    '${areaSets[areaSets.keys.toList()[_selectedAreaIndex[0] == -1 ? 0 : _selectedAreaIndex[0]]][i].name}',
                    style: TextStyle(
                      color: i == _selectedAreaIndex[1]
                          ? Theme.of(context).primaryColor
                          : Colors.black87,
                    ),
                  ),
                ),
              );
            },
            itemCount: areaSets[areaSets.keys.toList()[
                    _selectedAreaIndex[0] == -1 ? 0 : _selectedAreaIndex[0]]]
                .length,
            separatorBuilder: (BuildContext context, int index) => Divider(),
            padding: EdgeInsets.all(0),
          ),
        ),
      ],
    );
  }

  /// 医院选择器
  Widget _buildHospitalArea(StateSetter state, BuildContext context) {
    return ListView.separated(
      padding: EdgeInsets.all(0),
      itemBuilder: (c, i) {
        return InkWell(
          child: Container(
            height: 50,
            alignment: Alignment.centerLeft,
            margin: EdgeInsets.symmetric(horizontal: 16),
            child: Text(
              _hospitalList[i].hospitalName,
              style: TextStyle(
                  color: _selectedHospitalIndex == i
                      ? Theme.of(context).primaryColor
                      : Colors.black87),
            ),
          ),
          onTap: () {
            Navigator.pop(context);
            setState(() {
              _selectedHospitalIndex = i;
            });
            _fetchDoctorList();
          },
        );
      },
      separatorBuilder: (c, i) => Divider(),
      itemCount: _hospitalList.length,
    );
  }

  /// 科室选择器
  Widget _buildDepartmentSelector(StateSetter state, BuildContext context) {
    return ListView.separated(
        padding: EdgeInsets.all(0),
        itemBuilder: (c, i) {
          return InkWell(
            child: Container(
              height: 50,
              alignment: Alignment.centerLeft,
              margin: EdgeInsets.symmetric(horizontal: 16),
              child: Text(
                i == 0 ? '不限科室' : _departments[i - 1].label,
                style: TextStyle(
                    color: _selectedDepartmentIndex == i - 1
                        ? Theme.of(context).primaryColor
                        : Colors.black87),
              ),
            ),
            onTap: () {
              Navigator.pop(context);
              setState(() {
                if (i == 0) {
                  _selectedDepartmentIndex = null;
                } else {
                  _selectedDepartmentIndex = i - 1;
                }
              });
              _fetchDoctorList();
            },
          );
        },
        separatorBuilder: (c, i) => Divider(),
        itemCount: _departments.length + 1);
  }

  /// 预约类型选择器
  Widget _buildSelectSelector(StateSetter state, BuildContext context) {
    return ListView.separated(
        padding: EdgeInsets.all(0),
        itemBuilder: (c, i) {
          return InkWell(
            child: Container(
              height: 50,
              alignment: Alignment.centerLeft,
              margin: EdgeInsets.symmetric(horizontal: 16),
              child: Text(
                _selectedTypes[i],
                style: TextStyle(
                    color: _selectedType == i
                        ? Theme.of(context).primaryColor
                        : Colors.black87),
              ),
            ),
            onTap: () {
              Navigator.pop(context);
              setState(() {
                _selectedType = i;
                if (_selectedType == 0) {
                  _items = _allItems;
                } else {
                  _items = _allItems
                      .where((element) => element.whetherSelected == '${i - 1}')
                      .toList();
                }
                _selectedDoctorList.forEach((element) {
                  _items.removeWhere((e) => e.id == element.id);
                });
                _items.insertAll(0, _selectedDoctorList);
              });
            },
          );
        },
        separatorBuilder: (c, i) => Divider(),
        itemCount: _selectedTypes.length);
  }

  Widget _buildMaterialDialogTransitions(
      BuildContext context,
      Animation<double> animation,
      Animation<double> secondaryAnimation,
      Widget child) {
    Animation<Offset> custom;
    custom = Tween<Offset>(
      begin: Offset(0.0, 0.0),
      end: Offset(0.0, 0.0),
    ).animate(animation);
    return SlideTransition(
      position: custom,
      child: child,
    );
  }

  Widget _buildSection(String title, {GestureTapCallback onTap}) {
    return Expanded(
      child: InkWell(
        onTap: onTap,
        child: Container(
          height: 50,
          alignment: Alignment.center,
          child: Row(
            mainAxisSize: MainAxisSize.min,
            children: [
              Container(
                constraints: BoxConstraints(
                    maxWidth: MediaQuery.of(context).size.width / 4 - 30),
                child: Text(
                  title,
                  overflow: TextOverflow.ellipsis,
                ),
              ),
              Icon(Icons.keyboard_arrow_down, color: Colors.grey[700]),
            ],
          ),
        ),
      ),
    );
  }

  void _fetchDoctorList({Map<String, dynamic> condition}) async {
    Map<String, dynamic> params = {};
    params['doctorId'] = _bean.doctorId;
    params['freeTime'] = _bean.freeTime;
    params['morningAfternoon'] = _bean.morningAfternoon;

    /// 添加筛选条件
    if (_selectedAreaIndex[0] != -1) {
      if (_selectedAreaIndex[1] != -1) {
        params['areaId'] =
            areaSets[areaSets.keys.toList()[_selectedAreaIndex[0]]]
                    [_selectedAreaIndex[1]]
                .id;
      } else {
        params['areaId'] = areaSets.keys.toList()[_selectedAreaIndex[0]].id;
      }
    }
    if (_selectedDepartmentIndex != null) {
      params['sectionType'] = _departments[_selectedDepartmentIndex].value;
    }
    if (_selectedHospitalIndex != null) {
      params['hospitalId'] = _hospitalList[_selectedHospitalIndex].hospitalId;
    }
    if (condition != null) {
      params.addAll(condition);
    }
    var result = await XHttp.postJson(Urls.SELECT_DOCTOR_LIST, params);
    if (result != null) {
      var response = ListResponse.fromJson(result);
      if (response.code == 1) {
        var data = (response.data)
            .map((e) => Doctor.fromJson((e as Map<String, dynamic>)))
            .toList();
        Log.d(_tag, 'data: $data');
        if (mounted) {
          setState(() {
            // 过滤掉已选择的用户
            data.removeWhere((element) => _selectedDoctorList
                .map((e) => e.id)
                .toList()
                .contains(element.id));
            _allItems = data;
            // 移除自己。
            _allItems.removeWhere(
                (element) => element.doctorAccount.id == SPUtils.getUser().id);
            // 根据已约未约条件进行筛选。
            if (_selectedType == 0) {
              _items = _allItems;
            } else {
              _items = _allItems
                  .where((element) =>
                      element.whetherSelected == '${_selectedType - 1}')
                  .toList();
            }
            // 移除已选用户。
            _selectedDoctorList.forEach((element) {
              _items.removeWhere((e) => e.id == element.id);
            });
            // 加上已选用户
            _items.insertAll(0, _selectedDoctorList);
          });
        }
      } else {
        ToastUtil.show(response.msg, context);
      }
    }
  }

  void _post() async {
    DialogUtils.showWaitDialog(context);
    List<Map<String, dynamic>> appointmentReceiverList = [];
    _selectedDoctorList.forEach((element) {
      appointmentReceiverList.add({'doctorId': element.doctorAccount?.id});
    });
    _bean.appointmentReceiverList = appointmentReceiverList;
    var value = await XHttp.postJson(Urls.RECORD_ADD, _bean.toMap());
    Navigator.pop(context);
    if (value != null) {
      Map<String, dynamic> response = value as Map<String, dynamic>;
      if (response['code'] == 1) {
        DialogUtils.showAlertDialog(context, '预约成功', '您已经成功预约会诊',
            onPressed: () {
          Navigator.popUntil(context, ModalRoute.withName(HomePage.routeName));
        });
      } else {
        ToastUtil.show(response['msg'], context);
      }
    }
  }

  void _fetchHospitalList() async {
    Map<String, dynamic> params = {};
    if (_selectedAreaIndex[0] != -1) {
      params['areaId'] = areaSets.keys.toList()[_selectedAreaIndex[0]].id;
    }
    if (_selectedAreaIndex[1] != -1) {
      params['areaId'] = areaSets[areaSets.keys.toList()[_selectedAreaIndex[0]]]
              [_selectedAreaIndex[1]]
          .id;
    }
    var value = await XHttp.postJson(Urls.HOSPITAL_LIST, params);
    if (value != null) {
      ListResponse response = ListResponse.fromJson(value);
      if (response.code == 1) {
        _hospitalList =
            List.from(response.data.map((e) => Hospital.fromJson(e)));
        _allHospitalList.addAll(_hospitalList);
      } else {
        ToastUtil.show(response.msg, context);
      }
    }
  }

  /// 获取科室列表
  Future<void> _getDepartmentTypes() async {
    var data =
        await XHttp.postJson(sprintf(Urls.DICT_VALUES, ['section_type']));
    if (data != null) {
      ListResponse response = ListResponse.fromJson(data);
      if (response.code == 1) {
        if (mounted) {
          _departments =
              List.from(response.data.map((e) => Department.fromJson(e)));
        }
      }
    }
  }

  void _fetchAreaList() async {
    var value = await XHttp.get(Urls.AREA_LIST);
    if (value != null) {
      ListResponse response = ListResponse.fromJson(value);
      if (response.code == 1) {
        _areaList = List.from(response.data.map((e) => Area.fromJson(e)));
        _areaList.removeWhere((element) => element.type == '1');
        _areaList.forEach((element) {
          if (element.type == '2') {
            List<Area> cities = [];
            _areaList.forEach((element1) {
              if (element1.type == '3' && element1.parentId == element.id) {
                cities.add(element1);
              }
            });
            areaSets[element] = cities;
          }
        });
      }
    }
  }

  void _addFavorite(int index) async {
    User user = SPUtils.getUser();
    if (user != null) {
      DialogUtils.showWaitDialog(context);
      var data = await XHttp.postJson(Urls.FAVORITE_ADD, {
        'accountId': user.id,
        'recordId': _items[index].id,
        'recordType': 'doctor',
      });
      Navigator.pop(context);
      if (data != null) {
        Map<String, dynamic> response = data as Map<String, dynamic>;
        if (response['code'] == 1) {
          if (mounted) {
            setState(() {
              _items[index].whetherAppointed = '1';
            });
          }
        }
      }
    }
  }

  void _removeFavorite(int index) async {
    User user = SPUtils.getUser();
    if (user != null) {
      DialogUtils.showWaitDialog(context);
      var data = await XHttp.postJson(Urls.FAVORITE_REMOVE, {
        'accountId': user.id,
        'recordId': _items[index].id,
      });
      Navigator.pop(context);
      if (data != null) {
        Map<String, dynamic> response = data as Map<String, dynamic>;
        if (response['code'] == 1) {
          if (mounted) {
            setState(() {
              _items[index].whetherAppointed = '0';
            });
          }
        }
      }
    }
  }
}

enum SelectorType { area, hospital, department }
